package com.ljf.finance.domain.base;

import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.StringUtil;
import com.ljf.finance.infra.assembler.FinanceDatAccountReportDetailAssembler;
import com.ljf.finance.infra.assembler.FinanceDatAccountReportTypeAssembler;
import com.ljf.finance.infra.assembler.FinanceRelAccountReportDetailAssembler;
import com.ljf.finance.model.FinanceDatVirtualAccount;
import com.ljf.finance.vo.*;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 账户报表类型  基础服务
 *
 * @author LJF
 * @since 2024-12-07
 */
@Component
public class FinanceDatAccountReportTypeBaseService {

    /**
     * 构建报表数据
     *
     * @param reportType
     * @param reportDetailList
     * @param relReportDetailList
     * @param accountList
     * @return
     */
    public FinanceDatAccountReportTypeReportDataVO buildReportData(FinanceDatAccountReportTypeVO reportType, List<FinanceDatAccountReportDetailVO> reportDetailList, List<FinanceRelAccountReportDetailVO> relReportDetailList, List<FinanceDatVirtualAccountVO> accountList) {
        FinanceDatAccountReportTypeReportDataVO result = FinanceDatAccountReportTypeAssembler
                .INSTANCE.toReportDataVO(reportType);
        result.setDetailList(buildReportDataDetail(reportDetailList, relReportDetailList, accountList));
        return result;
    }

    /**
     * 构建报表数据-明细
     *
     * @param reportDetailList
     * @param relReportDetailList
     * @param accountList
     * @return
     */
    private List<FinanceDatAccountReportDetailReportDataVO> buildReportDataDetail(List<FinanceDatAccountReportDetailVO> reportDetailList, List<FinanceRelAccountReportDetailVO> relReportDetailList, List<FinanceDatVirtualAccountVO> accountList) {
        if (CollectionUtil.isEmpty(reportDetailList)) {
            return Collections.emptyList();
        }
        Map<String, FinanceDatVirtualAccountVO> accountMap = accountList.stream().collect(Collectors.toMap(FinanceDatVirtualAccount::getCode, Function.identity(), (a, b) -> a));
        List<FinanceDatAccountReportDetailReportDataVO> resultList = new ArrayList<>();
        reportDetailList.sort(Comparator.comparing(FinanceDatAccountReportDetailVO::getSort));
        int index = 1;
        BigDecimal totalLiabilities = BigDecimal.ZERO;
        BigDecimal totalProfit = BigDecimal.ZERO;
        for (FinanceDatAccountReportDetailVO detail : reportDetailList) {
            List<FinanceRelAccountReportDetailReportDataVO> resultAccountList = buildReportDataAccount(detail.getCode(), relReportDetailList, accountMap);
            BigDecimal liabilities = BigDecimal.ZERO;
            BigDecimal profit = BigDecimal.ZERO;
            for (FinanceRelAccountReportDetailReportDataVO detailReportData : resultAccountList) {
                if (detailReportData.getLiabilities() != null) {
                    liabilities = liabilities.add(detailReportData.getLiabilities());
                }
                if (detailReportData.getProfit() != null) {
                    profit = profit.add(detailReportData.getProfit());
                }
            }
            totalLiabilities = totalLiabilities.add(liabilities);
            totalProfit = totalProfit.add(profit);
            FinanceDatAccountReportDetailReportDataVO result = FinanceDatAccountReportDetailAssembler.INSTANCE.toReportDataVO(
                    detail,
                    liabilities.compareTo(BigDecimal.ZERO) == 0 ? null : liabilities,
                    profit.compareTo(BigDecimal.ZERO) == 0 ? null : profit,
                    liabilities.add(profit),
                    resultAccountList,
                    index++
            );
            resultList.add(result);
        }
        return resultList;
    }

    /**
     * 构建报表数据-账户
     *
     * @param detailCode
     * @param relReportDetailList
     * @param accountMap
     * @return
     */
    private List<FinanceRelAccountReportDetailReportDataVO> buildReportDataAccount(String detailCode, List<FinanceRelAccountReportDetailVO> relReportDetailList, Map<String, FinanceDatVirtualAccountVO> accountMap) {
        List<FinanceRelAccountReportDetailVO> dataList = relReportDetailList.stream()
                .filter(one -> StringUtil.equals(detailCode, one.getDetailCode())).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(dataList)) {
            return Collections.emptyList();
        }
        List<FinanceRelAccountReportDetailReportDataVO> resultList = new ArrayList<>();
        relReportDetailList.sort(Comparator.comparing(FinanceRelAccountReportDetailVO::getSort));
        for (FinanceRelAccountReportDetailVO detail : dataList) {
            FinanceDatVirtualAccountVO account = accountMap.get(detail.getAccountCode());
            FinanceRelAccountReportDetailReportDataVO result = FinanceRelAccountReportDetailAssembler.INSTANCE
                    .toReportDataVO(detail, account);
            if (account != null) {
                if (account.getAmount().compareTo(BigDecimal.ZERO) > 0) {
                    result.setProfit(account.getAmount());
                }
                else if (account.getAmount().compareTo(BigDecimal.ZERO) < 0) {
                    result.setLiabilities(account.getAmount());
                }
            }
            resultList.add(result);
        }
        return resultList;
    }

}
